#pragma once
#include<iostream>
#include<string>
#include<vector>
#include<pthread.h>
#include<sys/types.h>
#include<sys/socket.h>
#include"InetAddr.hpp"
#include"lockguard.hpp"
#include"threadpool.hpp"
using namespace std;
using task_t = function<void()>;
class Route
{
public:
	Route()
	{
		pthread_mutex_init(&_mutex,nullptr);
	};
	void Forward(int sockfd,string message,InetAddr who)
	{
		CheckOnline(who);
		if(message=="Q"||message=="QUIT")
		{
			Offline(who);
			return;
		}
		task_t t =bind(&Route::ForwardHander,this,sockfd,message,who);
		threadpool<task_t>::GetInstance()->push(t);

	};
	void CheckOnline(InetAddr who)
	{
		lockguard lg(&_mutex);
		for(auto user:_online_user)
		{
			if(user==who)
			{
				LOG(DEBUG,"%s is already exist!\n",who.AddrStr().c_str());
				return;
			}

		};
		_online_user.emplace_back(who);

	};
	void Offline(InetAddr who)
	{
		lockguard lg(&_mutex);
		auto iter = _online_user.begin();
		for(;iter<_online_user.end();iter++)
		{
			if(*iter==who)
			{
				LOG(INFO,"%s quit!\n",who.AddrStr().c_str());
				_online_user.erase(iter);
				return;
			}

		};

		

	};
	void ForwardHander(int sockfd,string message,InetAddr who)
	{
		lockguard lg(&_mutex);
		string send_message = who.AddrStr()+":"+message;
		for(auto user:_online_user)
		{
			struct sockaddr_in peer = user.Addr();
			LOG(INFO,"%s send message to %s\n",who.AddrStr().c_str(),user.AddrStr().c_str());
			sendto(sockfd,message.c_str(),message.size(),0,(struct sockaddr*)&peer,sizeof(peer));

		};
		

	};
	~Route()
	{
		pthread_mutex_destroy(&_mutex);
	};
private:
	vector<InetAddr> _online_user;
	pthread_mutex_t _mutex;
};
